/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.viewmodel.webapi;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.json.element.BizElementDeserializer;
import com.inspur.edp.bef.bizentity.json.element.BizElementSerializer;
import com.inspur.edp.bef.bizentity.json.operation.BizMgrActionCollectionDeserializer;
import com.inspur.edp.bef.bizentity.operation.BizMgrAction;
import com.inspur.edp.bef.bizentity.operation.BizOperationCollection;
import com.inspur.edp.bef.bizentity.operation.collection.BizMgrActionCollection;
import com.inspur.edp.bef.bizentity.util.StringUtil;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.json.element.GspAssociationSerializer;
import com.inspur.edp.cef.designtime.api.variable.CommonVariable;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonModel;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.element.GspCommonAssociation;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.action.ActionParamInfo;
import com.inspur.edp.formserver.viewmodel.collection.VMActionCollection;
import com.inspur.edp.formserver.viewmodel.common.ConvertUtils;
import com.inspur.edp.formserver.viewmodel.common.InitVoUtil;
import com.inspur.edp.formserver.viewmodel.common.LinkBeUtils;
import com.inspur.edp.formserver.viewmodel.common.MappingType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementMapping;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementSourceType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.formserver.viewmodel.dto.SaveViewModelDto;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.i18n.VMI8nResourceUtil;
import com.inspur.edp.formserver.viewmodel.i18n.names.VoResourceKeyNames;
import com.inspur.edp.formserver.viewmodel.json.element.ViewElementDeserializer;
import com.inspur.edp.formserver.viewmodel.json.model.ViewModelDeserializer;
import com.inspur.edp.formserver.viewmodel.json.model.ViewModelSerializer;
import com.inspur.edp.formserver.viewmodel.json.operation.VmActionCollectionSerializer;
import com.inspur.edp.formserver.viewmodel.util.ViewModelUtils;
import com.inspur.edp.formserver.vmapi.ViewModelService;
import com.inspur.edp.formserver.vmapi.dto.ViewModelExtendDto;
import com.inspur.edp.formserver.vmmanager.compcodebutton.CompButton;
import com.inspur.edp.formserver.vmmanager.service.UpdateVariableWithUdtService;
import com.inspur.edp.formserver.vmmanager.service.UpdateVirtualVoElementWithUdtService;
import com.inspur.edp.formserver.vmmanager.service.VmManagerService;
import com.inspur.edp.formserver.vmmanager.service.WebControllerService;
import com.inspur.edp.formserver.vmmanager.util.CheckComUtil;
import com.inspur.edp.formserver.vmmanager.util.CheckInfoUtil;
import com.inspur.edp.formserver.vmmanager.util.SimplifyMetadataUtil;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.GspProject;
import com.inspur.edp.lcm.metadata.api.entity.uri.MetadataURI;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.web.help.metadata.HelpMetadataContent;
import io.iec.edp.caf.commons.utils.CollectionUtils;
import lombok.var;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.stream.Collectors;

import static com.inspur.edp.formserver.viewmodel.common.ConvertUtils.toElement;
import static com.inspur.edp.formserver.viewmodel.common.ConvertUtils.toObject;

@Path("")
@Produces(MediaType.APPLICATION_JSON)
public class ViewModelController {
    // 元数据服务
    private final MetadataService metadataService;
    // 元数据依赖服务
    private final RefCommonService refCommonService;
    // 元数据工程服务
    private final MetadataProjectService metadataProjectService;
    // 文件服务
    private final FileService fileService;
    // 元数据视图模型服务
    private final ViewModelService viewModelService;

    public ViewModelController(MetadataService metadataService,
                               RefCommonService refCommonService,
                               MetadataProjectService metadataProjectService,
                               FileService fileService,
                               ViewModelService viewModelService) {
        this.metadataService = metadataService;
        this.refCommonService = refCommonService;
        this.metadataProjectService = metadataProjectService;
        this.fileService = fileService;
        this.viewModelService = viewModelService;
    }

    @Path("sysn")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void saveAndSysn(String metadataInfo) {
        ObjectMapper mapper = getViewModelMapper();

        try {
            JsonNode node = mapper.readTree(metadataInfo);
            isMetadataCodeExist(node);
            String path = node.get("path").textValue();
            String metadataName = null;
            if (!CheckInfoUtil.checkNull(node.get("name"))) {
                metadataName = node.get("name").textValue();
            }
            GspMetadata metadata = metadataService.loadMetadata(metadataName, path);
            //生成构件元数据
            ArrayList list = VmManagerService.generateComponent(metadata, path, true);
            //构件代码模板
            VmManagerService.generateComponentCode(metadata, path, list);
            //保存元数据
            VmManagerService.saveMetadata(metadata, path);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1001, e);
        }
    }

    @Path("isHelpComp")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public boolean isHelpComp(String info) {
        return true;
    }

    @Path("createVirtualVo")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String creataVirtualVo(String info) {
        ObjectMapper mapper = getViewModelMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String metadataID = node.get("metadataID").textValue();
            String metadataName = null;
            if (!CheckInfoUtil.checkNull(node.get("metadataName"))) {
                metadataName = node.get("metadataName").textValue();
            }
            String metadataCode = node.get("metadataCode").textValue();
            String metadataAssembly = node.get("metadataAssembly").textValue();
            GspViewModel vm = InitVoUtil
                    .BuildVirtualVo(metadataID, metadataName, metadataCode, metadataAssembly);
            return mapper.writeValueAsString(vm);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1002, e);
        }
    }

    @Path("convertBizEntity")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String convertBizEntityToViewModel(String convertBeInfo) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(convertBeInfo);
            String bizEntityJson = node.get("bizEntityJson").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }
            String relativePath = null;
            if (!CheckInfoUtil.checkNull(node.get("relativePath"))) {
                relativePath = node.get("relativePath").textValue();
            }
            String enableProcessItem = "0";
            if (!CheckInfoUtil.checkNull(node.get("enableProcessItem"))) {
                enableProcessItem = node.get("enableProcessItem").textValue();
            }

            String beId = node.get("beId").textValue();
            String voGeneratingAssembly = node.get("voGeneratingAssembly").textValue();
            return convertBizEntityToViewModel(bizEntityJson, bePkgName, beId, voGeneratingAssembly, enableProcessItem, relativePath);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1003, e);
        }

    }

    @Path("chooseUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateUdtElementWhenChooseUdt(String info) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String refUdtId = node.get("refUdtId").textValue();
            String path = node.get("path").textValue();
            String beElementJson = node.get("udtElementJson").textValue();
            return UpdateVariableWithUdtService
                    .getInstance().updateVariableWithRefUdt(node, refUdtId, path, beElementJson, true);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1004, e);
        }

    }

    @Path("updateUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateUdtElementWhenLoading(String info) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String refUdtId = node.get("refUdtId").textValue();
            String path = node.get("path").textValue();
            String beElementJson = node.get("udtElementJson").textValue();
            return UpdateVariableWithUdtService.getInstance().updateVariableWithRefUdt(node, refUdtId, path, beElementJson, false);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1005, e);
        }

    }

    @Path("virtualVoChooseUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateVirtualVoUdtElementWhenChooseUdt(String info) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String refUdtId = node.get("refUdtId").textValue();
            String path = node.get("path").textValue();
            String beElementJson = node.get("udtElementJson").textValue();
            return UpdateVirtualVoElementWithUdtService
                    .getInstance().UpdateVariableWithRefUdt(node, refUdtId, path, beElementJson, true);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1006, e);
        }

    }

    @Path("virtualVoUpdateUdt")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String updateVirtualVoUdtElementWhenLoading(String info) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String refUdtId = node.get("refUdtId").textValue();
            String path = node.get("path").textValue();
            String beElementJson = node.get("udtElementJson").textValue();
            return UpdateVirtualVoElementWithUdtService
                    .getInstance().UpdateVariableWithRefUdt(node, refUdtId, path, beElementJson, false);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1007, e);
        }

    }


    @Path("changeMainObj")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String changeMainObj(String convertBeInfo) {
        ObjectMapper mapper = getViewModelMapper();
        try {
            JsonNode node = mapper.readTree(convertBeInfo);
            String newObjId = node.get("newObjId").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }

            String beId = node.get("beId").textValue();
            String voGeneratingAssembly = node.get("voGeneratingAssembly").textValue();
            GspMetadata metadata = WebControllerService.getMetadata(node, null, bePkgName, beId);
            // 克隆以防止修改缓存中对象
            GspBusinessEntity be = ((GspBusinessEntity) metadata.getContent()).clone();
            GspBizEntityObject bizObj = (GspBizEntityObject) be.findObjectById(newObjId);
            if (bizObj == null) {
                throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1008, null, be.getCode(), be.getName(), newObjId);
            }
            // 处理子节点
            if (bizObj.getObjectType() == GspCommonObjectType.ChildObject) {
                bizObj.setObjectType(GspCommonObjectType.MainObject);
                bizObj.getKeys().clear();
                be.setMainObject(bizObj);
            }
            GspViewModel vm = ConvertUtils.convertToViewModel(be, bePkgName, beId, voGeneratingAssembly);
            String vmJson = mapper.writeValueAsString(vm);
            return vmJson;
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1009, e);
        }
    }


    @Path("getHelpVoTargetBeId")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getHelpVoTargetBeId(String convertBeInfo) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(convertBeInfo);
            String helperId = node.get("helperId").textValue();
            MetadataURI targetHelpURI = new MetadataURI();
            targetHelpURI.setId(helperId);
            GspMetadata helpMetadata = refCommonService.getRefMetadata(targetHelpURI, null, "");
            HelpMetadataContent helpMetadataContent = (HelpMetadataContent) helpMetadata.getContent();
            String voId = helpMetadataContent.getDataSource().getVoSourceId();
            MetadataURI targetVOURI = new MetadataURI();
            targetVOURI.setId(voId);
            GspMetadata refVOMetadata = refCommonService.getRefMetadata(targetVOURI, null, "");
            GspViewModel helpVo = (GspViewModel) refVOMetadata.getContent();
            if (helpVo == null) {
                throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1010, null,
                        helpMetadataContent.getCode(), helpMetadataContent.getName(),
                        helpMetadataContent.getDataSource().getSourceType());
            }
            if (helpVo.getMapping() == null || helpVo.getMapping().getMapType() != MappingType.BizEntity) {
                throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1011, null,
                        helpMetadataContent.getCode(), helpMetadataContent.getName());
            }
            return "\"" + helpVo.getMapping().getTargetMetadataId() + "\"";
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1012, e);
        }
    }


    @Path("convertBeElements")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String convertBeElementIdsToVmElements(String convertEleInfo) {
        return WebControllerService.getInstance().convertBeElementIdsToVmElements(convertEleInfo, false);
    }

    @Path("getBeAsso")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getBizAssoById(String info) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        BizElementSerializer bizElementSerializer = new BizElementSerializer();
        GspAssociationSerializer associationDeserializer = new GspAssociationSerializer(bizElementSerializer);
        module.addSerializer(GspAssociation.class, associationDeserializer);
        mapper.registerModule(module);
        try {
            JsonNode node = mapper.readTree(info);
            String path = node.get("path").textValue();
            String voEleMappingJson = node.get("voEleMapping").textValue();
            String beAssoId = node.get("assoId").textValue();
            GspVoElementMapping voEleMapping = WebControllerService.getInstance().readVoEleMapping(voEleMappingJson);
            GspCommonAssociation bizAsso = WebControllerService.getInstance().getBizAsso(node, path, voEleMapping, beAssoId, false);

            String bizAssoJson = mapper.writeValueAsString(bizAsso);
            return bizAssoJson;
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1013, e);
        }
    }

    @Path("getVoAsso")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getVoAsso(String info) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(info);
            String path = node.get("path").textValue();
            String voEleMappingJson = node.get("voEleMapping").textValue();
            String beAssoJson = node.get("beAsso").textValue();
            String voAssoJson = node.get("voAsso").textValue();
            String refElementIdsJson = node.get("refElementIds").textValue();


            GspCommonAssociation beAsso = WebControllerService.getInstance().readAsso(beAssoJson, new BizElementDeserializer());
            GspCommonAssociation originVoAsso = WebControllerService.getInstance().readAsso(voAssoJson, new ViewElementDeserializer());
            GspVoElementMapping voEleMapping = WebControllerService.getInstance().readVoEleMapping(voEleMappingJson);
            var refElementIds = WebControllerService.getInstance().readIdList(refElementIdsJson);

            if (CollectionUtils.isEmpty(refElementIds)) {
                throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1014, null);
            }

            GspFieldCollection bizRefElements = beAsso.getRefElementCollection();
            GspFieldCollection originVoRefElements = originVoAsso.getRefElementCollection();
            GspElementCollection refElements = new GspElementCollection(null);

            for (var refElementId : refElementIds) {
                IGspCommonElement voRefElement = (IGspCommonElement) originVoRefElements.stream().filter(item -> item.getRefElementId().equals(refElementId)).findFirst().orElse(null);
                if (!(voRefElement instanceof GspViewModelElement)) {
                    IGspCommonElement beRefElement = (IGspCommonElement) bizRefElements.stream().filter(item -> item.getRefElementId().equals(refElementId)).findFirst().orElse(null);
                    if (!(beRefElement instanceof GspBizEntityElement)) {
                        throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1015, null, refElementId);
                    } else {
                        refElements.add(toElement(beRefElement, voEleMapping.getTargetMetadataPkgName(), voEleMapping.getTargetMetadataId(), voEleMapping.getSourceType()));
                    }
                } else {
                    refElements.add(voRefElement);
                }
            }
            return WebControllerService.getInstance().writeViewElementsJson(refElements);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1016, e);
        }

    }

    @Path("getVirtualVoAsso")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getVirtualVoAsso(String info) {
        try {
            return WebControllerService.getInstance().getVirtualVoAsso(info, false);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1035, e);
        }
    }

    @Path("convertActions")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String convertBizActionsToVmActions(String convertActionInfo) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(convertActionInfo);
            String bizActionsJson = node.get("bizActionsJson").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }
            String beId = node.get("beId").textValue();
            return convertBizActionsToVmActions(bizActionsJson, bePkgName, beId);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1017, e);
        }
    }

    @Path("convertElements")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String convertBizElementsToVmElements(String convertActionInfo) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(convertActionInfo);
            String bizElementsJson = node.get("bizElementsJson").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }
            String beId = node.get("beId").textValue();
            return convertBizActionsToVmActions(bizElementsJson, bePkgName, beId);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1018, e);
        }
    }

    @Path("getbizObject/{beid}/{objid}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getBizObject(@PathParam("beid") String beid, @PathParam("objid") String objid, @QueryParam("path") String path, @QueryParam("bePkgName") String bePkgName) {
        GspMetadata metadata = WebControllerService.getMetadata(null, path, bePkgName, beid);
        GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
        return WebControllerService.getInstance().getBizObject(be, objid);
    }

    @Path("addObjects")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String addBizObjects(String convertActionInfo) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonModel.class, new ViewModelSerializer());
        module.addDeserializer(IGspCommonModel.class, new ViewModelDeserializer());
        mapper.registerModule(module);
        try {
            JsonNode node = mapper.readTree(convertActionInfo);
            String vmJson = node.get("vmJson").textValue();
            String bizObjIdsJson = node.get("bizObjIds").textValue();
            String path = node.get("path").textValue();
            String bePkgName = null;
            if (!CheckInfoUtil.checkNull(node.get("bePkgName"))) {
                bePkgName = node.get("bePkgName").textValue();
            }
            String beId = node.get("beId").textValue();

            List<String> bizObjIds = WebControllerService.getInstance().readIdList(bizObjIdsJson);
            GspMetadata metadata = WebControllerService.getMetadata(node, path, bePkgName, beId);
            GspBusinessEntity be = (GspBusinessEntity) metadata.getContent();
            GspViewModel vm = mapper.readValue(vmJson, GspViewModel.class);
            List<String> allBizObjIds = be.getAllObjectList().stream().map(item -> item.getID()).collect(
                    Collectors.toList());//.Select(item => item.ID).ToList();
            List<String> vmObjMappingIds = vm.getAllObjectList().stream().map(item -> ((GspViewObject) item).getMapping().getTargetObjId()).collect(
                    Collectors.toList());//.Select(item => ((GspViewObject)item).Mapping.TargetObjId).ToList();

            List<String> newVmMappingObjIds = bizObjIds.stream().filter(item -> !vmObjMappingIds.contains(item)).collect(Collectors.toList());//.Where(item => !vmObjMappingIds.Contains(item)).ToList();
            if (newVmMappingObjIds.size() == 0) {
                return mapper.writeValueAsString(vm);
            }

            // 删除未选中的be对象
            var redundantBizObjIds = allBizObjIds.stream().filter(item -> !vmObjMappingIds.contains(item)).collect(Collectors.toList());//.Where(item => !bizObjIds.Contains(item)).ToList();
            removeRedundantBizObj(be, redundantBizObjIds);

            // 添加新增的be对象
            addNewBizObject(vm, be, newVmMappingObjIds, vmObjMappingIds);
            return mapper.writeValueAsString(vm);
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1019, e);
        }
    }

    private void addNewBizObject(GspViewModel vm, GspBusinessEntity be, List<String> newVmMappingObjIds,
                                 List<String> vmObjMappingIds) {
        if (newVmMappingObjIds.size() != 0) {
            List<String> ids = newVmMappingObjIds;
            for (String id : ids) {
                IGspCommonObject bizObj = getObjectById(be, id);
                String parentObjId = bizObj.getParentObject().getID();
                if (vmObjMappingIds.contains(parentObjId)) {
                    IGspCommonObject parentObj = getMappedObjectById(vm, parentObjId);
                    if (parentObj == null)
                        throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1020, null, parentObjId);
                    parentObj.getContainChildObjects().add(
                            toObject(bizObj, vm.getMapping().getTargetMetadataPkgName(), vm.getMapping().getTargetMetadataId(), parentObj.getIDElement().getID(), GspVoObjectSourceType.BeObject));
                }
            }
        }
    }

    private IGspCommonObject getObjectById(IGspCommonModel cm, String id) {
        return cm.getAllObjectList().stream().filter((item) -> item.getID().equals(id)).findFirst().orElse(null);//;.Find(obj => obj.ID == id);
    }

    private IGspCommonObject getMappedObjectById(GspViewModel vm, String id) {
        return vm.getAllObjectList().stream().filter((item) -> ((GspViewModel) item).getMapping().getTargetObjId().equals(id)).findFirst().orElse(null);//.Find(obj => ((GspViewObject)obj).Mapping.TargetObjId == id);
    }

    private void removeRedundantBizObj(GspBusinessEntity be, List<String> redundantBizObjIds) {
        if (redundantBizObjIds.size() != 0) {
            for (String id : redundantBizObjIds) {
                IGspCommonObject childObj = getObjectById(be, id);
                if (childObj == null)
                    continue;
                childObj.getParentObject().getContainChildObjects().remove(childObj);
            }
        }
    }

    @Path("addObject")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String addBizObject(String addObjInfo) {
        return WebControllerService.getInstance().addBizObject(addObjInfo, false);
    }

    @Path("batchSimplification")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void SimplifyMetadata() {
        SimplifyMetadataUtil util = new SimplifyMetadataUtil();
        util.Simplify();
    }


    private String convertBizActionsToVmActions(String bizActionsJson, String bePkgName,
                                                String beId) {
        VMActionCollection vmActions = new VMActionCollection();
        BizMgrActionCollection bizMgrActions = readBizMgrActions(bizActionsJson);
        if (bizMgrActions.getCount() > 0) {
            bizMgrActions.forEach(mgrAction -> {
                var vmAction = ConvertUtils.toMappedAction((BizMgrAction) mgrAction, beId, bePkgName);
                vmActions.add(vmAction);
            });
        }
        return writeViewObjectsJson(vmActions);
    }

    private String writeViewObjectsJson(VMActionCollection vmActions) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(VMActionCollection.class, new VmActionCollectionSerializer());
        mapper.registerModule(module);
        try {
            String vmActionsJson = mapper.writeValueAsString(vmActions);
            return vmActionsJson;
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1021, e);
        }
    }

    private BizMgrActionCollection readBizMgrActions(String bizActionsJson) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(BizOperationCollection.class, new BizMgrActionCollectionDeserializer());
        mapper.registerModule(module);
        try {
            BizMgrActionCollection bizOperations = (BizMgrActionCollection) mapper.readValue(bizActionsJson, BizOperationCollection.class);
            return bizOperations;
        } catch (Exception e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1022, e);
        }
    }


    public static GspElementCollection convertPartialElementsToVoElements(IGspCommonObject co, List<String> eleIdList, String pkgName, String metaId, GspVoElementSourceType sourceType) {
        GspElementCollection voElements = new GspElementCollection(null);
        if (eleIdList != null && eleIdList.size() > 0) {
            for (String eleId : eleIdList) {
                GspBizEntityElement bizElement = (GspBizEntityElement) co.findElement(eleId);
                GspViewModelElement voElement = toElement(bizElement, pkgName, metaId, sourceType);
                voElement.getMapping().setTargetObjectId(co.getID());
                voElements.add(voElement);
            }
        }
        return voElements;
    }

    private ObjectMapper getViewModelMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonModel.class, new ViewModelSerializer());
        module.addDeserializer(IGspCommonModel.class, new ViewModelDeserializer());
        mapper.registerModule(module);
        return mapper;
    }

    private String convertBizEntityToViewModel(String bizEntityJson, String bePkgName, String beId,
                                               String voGeneratingAssembly, String enableProcessItem,String relativePath) {
        GspBusinessEntity be;
        try {
            be = new ObjectMapper().readValue(bizEntityJson, GspBusinessEntity.class);
            GspViewModel vm = ConvertUtils.convertToViewModel(be, bePkgName, beId, voGeneratingAssembly,relativePath);
//       联动vo的关联带出字段枚举信息
            LinkBeUtils linkBeUtils = new LinkBeUtils();
            linkBeUtils.linkBeRefElements(vm);
            if (enableProcessItem.equals("1")) {
                CommonVariable variable = new CommonVariable();
                variable.setID(UUID.randomUUID().toString());
                variable.setCode("bffSysFormConfigId");
                variable.setLabelID("bffSysFormConfigId");
                variable.setName(VMI8nResourceUtil.getMessage(VoResourceKeyNames.FROM_PROCESS_CONFIG));
                variable.setMDataType(GspElementDataType.forValue(0));
                variable.setLength(36);
                vm.getVariables().getContainElements().addField(variable);
            }
            return new ObjectMapper().writeValueAsString(vm);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1023, e);
        }
    }

    private GspBusinessEntity getBizEntity(String path, String bePkgName, String beId) {

        if (ViewModelUtils.checkNull(beId)) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1024, null);
        }
        GspMetadata metadata = refCommonService.getRefMetadata(beId);
        if (!(metadata.getContent() instanceof GspBusinessEntity)) {
            throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1025, null, beId);
        }
        return (GspBusinessEntity) metadata.getContent();
    }

    /**
     * 获取VO动作构件代码路径
     *
     * @param info
     * @return
     */
    @Path("VOComponentCodePath")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getVOComponentCodePath(JsonNode info) {
        String id = info.get("metadataId").textValue();
        String projectpath = info.get("metadataPath").textValue();
        String type = info.get("actionType").textValue();
        String action = info.get("actionCode").textValue();
        ArrayList<String> actionList = new ArrayList<>();
        actionList.add(action);
        GspMetadata metadata = metadataService.loadMetadataByMetadataId(id, projectpath);
        GspViewModel vo = (GspViewModel) metadata.getContent();
        String relativePath = metadata.getRelativePath();

        GspProject metadataProj = metadataService.getGspProjectInfo(relativePath);
        String compAssemblyName = metadataProj.getProjectNameSpace();

        CompButton button = new CompButton();
        ActionParamInfo paramInfo = new ActionParamInfo();
        paramInfo.setMetadata(metadata);
        String filePath = button.getCompPath(paramInfo, vo, type, relativePath, actionList, compAssemblyName);
        filePath.replaceAll("\\\\", Matcher.quoteReplacement(File.separator));
        filePath.replaceAll("/", Matcher.quoteReplacement(File.separator));

        return filePath;
    }

    /**
     * 获取VO动作构件代码
     *
     * @param info
     * @return
     */
    @Path("VOComponentCode")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public String getVOComponentCode(JsonNode info) {
        String id = info.get("metadataId").textValue();
        String projectpath = info.get("metadataPath").textValue();
        String type = info.get("actionType").textValue();
        String action = info.get("actionCode").textValue();
        ArrayList<String> actionList = new ArrayList<>();
        actionList.add(action);
        GspMetadata metadata = metadataService.loadMetadataByMetadataId(id, projectpath);
        GspViewModel vo = (GspViewModel) metadata.getContent();
        String relativePath = metadata.getRelativePath();
        GspProject metadataProj = metadataService.getGspProjectInfo(relativePath);
        String compAssemblyName = metadataProj.getProjectNameSpace();

        CompButton button = new CompButton();
        ActionParamInfo paramInfo = new ActionParamInfo();
        paramInfo.setMetadata(metadata);
        String code = button.getCompCode(paramInfo, vo, type, relativePath, actionList, compAssemblyName);

        return code;
    }

    /**
     * 判断当前元数据是否在当前BO内
     *
     * @param info
     * @return
     */
    @Path("isMetadataExist")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public boolean isMetadataExist(JsonNode info) {
        if (StringUtil.checkNull(info)) {
            return false;
        }
        String path = info.get("path").textValue();
        String metadataFileName = info.get("metadataFileName").textValue();
        return metadataService.isMetadataExist(path, metadataFileName);
    }

    private void isMetadataCodeExist(JsonNode info) {
        if (StringUtil.checkNull(info)) {
            return;
        }
        String metadataName = info.get("name").textValue();
        String projectPath = info.get("path").textValue();

        GspMetadata metadata = metadataService.loadMetadata(metadataName, projectPath);
        GspViewModel vo = (GspViewModel) metadata.getContent();
        List<CheckComUtil> checkInfo = new ArrayList<>();
        CompButton button = new CompButton();
        button.getNewActions(vo, checkInfo);
        String relativePath = metadata.getRelativePath();
        String compModulePath = metadataProjectService.getJavaCompProjectPath(relativePath);
        GspProject metadataProj = metadataService.getGspProjectInfo(relativePath);
        String compAssemblyName = metadataProj.getProjectNameSpace();
        if (checkInfo.size() <= 0) {
            return;
        }

        for (CheckComUtil checkComUtil : checkInfo) {
            ArrayList<String> actionList = new ArrayList<>();
            actionList.add(checkComUtil.getAction());
            String filePath = button.getFilePath(vo, checkComUtil, compModulePath, compAssemblyName);
            filePath.replaceAll("\\\\", Matcher.quoteReplacement(File.separator));
            filePath.replaceAll("/", Matcher.quoteReplacement(File.separator));
            if (fileService.isFileExist(filePath)) {
                String fileName = "";
                if (!"VarDeterminations".equals(checkComUtil.getType())) {
                    fileName = checkComUtil.getAction() + "VOAction.java";
                } else {
                    fileName = vo.getName() + "Variable" + checkComUtil.getAction() + "VODtm.java";
                }
                throw new ViewModelException(VoWebApiErrorCodes.GSP_VIEWOBJECT_WEBAPI_1026, null, filePath, fileName, checkComUtil.getAction(), checkComUtil.getActionName(), checkComUtil.getType());
            }
        }
    }

    @Path("loadViewModel")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public ViewModelExtendDto loadViewModel(@QueryParam(value = "viewModelId")String viewModelId) {
        return viewModelService.getViewModelExtendInfo(viewModelId);
    }
    @Path("saveViewModel")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public void saveViewModel(SaveViewModelDto saveViewModelAuthInfo) {
        viewModelService.saveViewModelExtendInfo(
                saveViewModelAuthInfo.getViewModelId(),
                saveViewModelAuthInfo.getViewModelExtendInfo(),
                saveViewModelAuthInfo.getAuthIdsToDelete());
    }
}
